import { CombatEventPool } from "@/Battle/Event/CombatEventPool.js";
export default class CombatEventBus{
    static _listeners=new Map();
    static _events=[];

    //中断节点
    static _interrupted_handlers=[];
    static _interrupted_index=-1;
    static _interrupted_event=null;

    static on(type,handler){
        let handlers=this._listeners.get(type);
        if(!handlers){
            handlers=[];
            this._listeners.set(type,handlers);
        }
        if(handlers.indexOf(handler)==-1){
            handlers.push(handler);
        }
    }

    static off(type,handler){
        let handlers=this._listeners.get(type);
        if(!handlers)return;
        let index=handlers.indexOf(handler);
        if(index!=-1){
            handlers.splice(index,1);
        }
    }

    static dispatch(event,onaccept,onreject){
        if(event){
            event.onaccept=onaccept;
            event.onreject=onreject;
            this._events.push(event);
        }
    }

    static processEvents(){
        if(this._events.length>0||this._interrupted_event){
            let event=null;
            let handlers=null;
            let index=0;
            if(this._interrupted_event){
                event=this._interrupted_event;
                handlers=this._interrupted_handlers;
                index=this._interrupted_index;
                event.resume();
                this._interrupted_event=null;
            }else{
                event=this._events.shift();
                handlers=this._listeners.get(event.type);
            }
            if(handlers){
                for(let i=index;i<handlers.length;++i){
                    handlers[i](event);
                    if(event.isInterrupted()){
                        this.saveInterruptNode(event,handlers,i+1);
                        return;
                    }
                }
            }
            
            this._dealEvent(event);
        }
    }

    static processPendingEvent(event){
        let parent=event.parent;
        if(parent){
            parent.tryCancelPending(event);
            this._dealEvent(parent);
        }
    }

    static _dealEvent(event){
        let havedecide=false;
        if(event.isAccepted()){
            event.onaccept?.();
            havedecide=true;
        }else if(event.isRejected()){
            event.onreject?.();
            havedecide=true;
        }
        if(havedecide||event.isPendingEnd()){
            this.processPendingEvent(event);
        }
        if(havedecide){
            CombatEventPool.releaseCombatEvent(event);
        }
    }

    static saveInterruptNode(event,handlers,index){
        this._interrupted_handlers=handlers;
        this._interrupted_index=index;
        this._interrupted_event=event;
    }

    static clear(){
        this._listeners.clear();
        this._events.length=0;
        this._interrupted_handlers.length=0;
        this._interrupted_event=null;
        CombatEventPool.clear();
    }
}